<?php


namespace App\Utils;


use App\Http\Logic\Common\Audit;
use App\Http\Logic\Common\AuditReadLogic;
use App\Http\Logic\System\AdminUserLogic;
use App\Models\Attachements;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;

class Helper
{
    /**
     * 获取当前路由对应的权限判断路由名
     * @param string $method
     * @param Request|null $request
     * @return string
     */
    public static function resolvePermissionRouteName($method = null, Request $request = null): string
    {
//        return Route::currentRouteName();
//        if($method == 'storage') return false;//暂存功能隐藏
        $request = $request ?? request();
        $actionMethod = $request->route()->getActionMethod();
        $method = $method ?? $actionMethod;
        $routeName = Route::currentRouteName();

        if(static::resolvePermissionActionMethod($method)=='update' ||
            static::resolvePermissionActionMethod($method)=='store' ||
            static::resolvePermissionActionMethod($method)=='index' ||
            static::resolvePermissionActionMethod($method)=='export' ||
            static::resolvePermissionActionMethod($method)=='all'
        )
        {
            return substr_replace(
                $routeName,
                static::resolvePermissionActionMethod($method),
                strlen($routeName) - strlen($actionMethod)
            );
        }else{
            return $routeName;
        }

    }
    /**
     * 获取当前路由对应的权限判断路由名
     * @param string $method
     * @param Request|null $request
     * @return string
     */
    public static function resolvePermissionName($method = null, Request $request = null): string
    {
        $request = $request ?? request();
        $actionMethod = $request->route()->getAction()['as'];
        $actionMethod_array = explode('.',$actionMethod);
        $method = $method ?? $actionMethod;
        $routeName = $request->route()->getName();

        return substr_replace(
            $routeName,
            static::resolvePermissionActionMethod($method),
            strlen($routeName) - strlen($actionMethod_array[count($actionMethod_array)-1])
        );
    }
    /**
     * 转换为对应权限的路由方法名
     * @param string $method
     * @return string
     */
    public static function resolvePermissionActionMethod(string $method): string
    {
        switch ($method) {
            case 'show':
                return 'index';
            case 'edit':
                return 'update';
            case 'create':
                return 'store';
            default:
                return $method;
        }
    }

    /**
     * array to tree
     * @param array $data
     * @param string $pidField
     * @param string $childrenField
     * @param int $rootId
     * @return array
     */
    public static function category(
        array  $data,
        string $pidField = 'pid',
        string $childrenField = 'children',
        int    $rootId = 0
    ): array
    {
        $list = [];
        foreach ($data as $v) {
            $list[$v['id']] = $v;
        }

        $tree = [];
        foreach ($list as $v) {
            if (isset($list[$v[$pidField]])) {
                if (!isset($list[$v[$pidField]][$childrenField])) {
                    $list[$v[$pidField]][$childrenField] = [];
                }
                $list[$v[$pidField]][$childrenField][] = &$list[$v['id']];
            } else if ($v[$pidField] == $rootId) {
                $tree[] = &$list[$v['id']];
            }
        }

        return $tree;
    }

    /**
     * @param array $data
     * @param array $except
     * @return array
     */
    public static function filterUnderlineParameter(array $data, array $except = []): array
    {
        $keys = array_filter(array_keys($data), function ($v) use ($except) {
            return in_array($v, $except) || substr($v, 0, 1) != '_';
        });
        return array_intersect_key($data, array_flip($keys));
    }

    /**
     * @return string
     */
    public static function getCurrentPageIndexUrl(): string
    {
        $method = request()->route()->getActionMethod();
        $routeName = request()->route()->getName();
        $indexRoute = substr(
            $routeName,
            0,
            strlen($routeName) - strlen(Str::snake($method)));
        $indexRoute .= 'index';

        return route($indexRoute);
    }

    public static function getCurrentPageCreateUrl():string
    {
        $method = request()->route()->getActionMethod();
        $routeName = request()->route()->getName();
        $indexRoute = substr(
            $routeName,
            0,
            strlen($routeName) - strlen(Str::snake($method)));
        $indexRoute .= 'create';

        return route($indexRoute);
    }
    public static function getCurrentPageStorageUrl():string
    {
        $method = request()->route()->getActionMethod();
        $routeName = request()->route()->getName();
        $indexRoute = substr(
            $routeName,
            0,
            strlen($routeName) - strlen(Str::snake($method)));
        $indexRoute .= 'storage';

        return route($indexRoute);
    }

    /**
     * @param array $data
     * @return array
     */
    public static function validateDataRepeat(array $data): array
    {
        return array_keys(
            array_filter(
                array_count_values($data),
                function ($v) {
                    return $v > 1;
                }
            )
        );
    }

    /**
     * @param $data
     * @param array $arr
     * @return array
     */
    public static function validateDataInArray($data, array $arr): array
    {
        if (!is_array($data)) {
            $data = array($data);
        }
        $data = array_unique($data);

        return array_diff($data, $arr);
    }

    /**
     * @param array $data
     * @param string $field
     * @param int $limit
     * @return string
     */
    public static function formatRepeatArrayToString(array $data, string $field = '', int $limit = 5): string
    {
        $count = count($data);
        if ($count <= $limit) {
            return trans('common.data_repeat', [
                'data' => '【' . implode('】【', $data) . '】',
                'field' => $field
            ]);
        }

        return trans('common.data_repeat_more', [
            'data' => '【' . implode('】【', array_slice($data, 0, $limit)) . '】',
            'field' => $field,
            'count' => $count
        ]);
    }

    /**
     * @param array $data
     * @param string $field
     * @param int $limit
     * @return string
     */
    public static function formatInvalidArrayToString(array $data, string $field = '', int $limit = 5): string
    {
        $count = count($data);
        if ($count <= $limit) {
            return trans('common.data_invalid', [
                'data' => '【' . implode('】【', $data) . '】',
                'field' => $field
            ]);
        }

        return trans('common.data_invalid_more', [
            'data' => '【' . implode('】【', array_slice($data, 0, $limit)) . '】',
            'field' => $field,
            'count' => $count
        ]);
    }

    /**
     * @param array $data
     * @param string $field
     * @param int $limit
     * @return string
     */
    public static function formatExistArrayToString(array $data, string $field = '', int $limit = 5): string
    {
        $count = count($data);
        if ($count <= $limit) {
            return trans('common.data_exist', [
                'data' => '【' . implode('】【', $data) . '】',
                'field' => $field
            ]);
        }

        return trans('common.data_exist_more', [
            'data' => '【' . implode('】【', array_slice($data, 0, $limit)) . '】',
            'field' => $field,
            'count' => $count
        ]);
    }

    /**
     * @param string $str
     * @return string
     */
    public static function formatParentheses(string $str): string
    {
        return str_replace(['（', '）'], ['(', ')'], $str);
    }

    /**
     * @param string $type
     * @param string $label
     * @param array|string $dateset 自定义数据，全部带入请求参数
     * @param string $title
     * @param int $labelLength
     * @param array $attributes 可用属性 width,height,title,z-index
     * @param string $classes
     * @return string
     */
    public static function detailHtml(
        string       $type,
        string       $label,
        array|string $dateset,
        string       $title = '',
        int          $labelLength = 20,
        array        $attributes = [],
        string       $classes = 'btn-info'
    ): string
    {
        $html = '<button type="button" class="open-show-detail shadow-none btn btn-sm ' . $classes . '"';
        if (strip_tags($label) == $label) {
            $label = mb_strlen($label) > $labelLength ? mb_substr($label, 0, $labelLength) . '...' : $label;
        }
        $dateset = is_array($dateset) ? $dateset : [$dateset => $label];
        $defaultAttributes = [
            'title' => $title ?: $label,
            'width' => '80vw',
            'height' => '80vh',
            'z-index' => 1100
        ];
        $forceAttributes = ['type' => $type];
        $attributes = array_merge($defaultAttributes, $attributes, $forceAttributes);
        foreach ($dateset as $k => $v) {
            $html .= ' data-' . $k . '="' . $v . '"';
        }
        foreach ($attributes as $k => $v) {
            $html .= ' detail-' . $k . '="' . $v . '"';
        }
        $html .= ' style="white-space: nowrap;">' . $label . '</button>';
        return $html;
    }

    /**
     * @param array|string $path
     * @return string
     */
    public static function filePreviewHtml(array|string $path, string $name, bool $read, bool $download): string
    {
        $host = \request()->path();
        $host = explode('/',$host);
        $html = array_reduce((array)$path, fn($carry, $v) => $carry . self::singleFilePreviewHtml($v, $name, $read, $download), '');
        if ($download && !empty($html)){
            $html .= '<a href="' . admin_url('file/download_all/?id=' . ($host[4] ?? '')) . '"  target="_blank">' . trans('common.download_all') . '</a>';
        }

        return $html;
    }
    /**
     * @param array|string $path
     * @return string
     */
    public static function filePreviewHtmlData(array|string $path, string $name, bool $read, bool $download,int $type = 1): array
    {
        $host = \request()->path();
        $host = explode('/',$host);
        $res = [];
        $res['html'] = array_map(fn($v) => self::singleFilePreviewHtmlData($v, $name, $read, $download), $path);
        if ($download && !empty($res['html'])){
            $res['all'] = '<a href="' . admin_url('file/download_all/?id=' . ($host[4] ?? '')) . '&type='.$type.'"  target="_blank">
              <span class="feather icon-download">'
                . trans('common.download_all') . '
</span></a>';
        }
        return $res;
    }
    /**
     * @param string $path
     * @return string
     */
    public static function singleFilePreviewHtmlData(string $path, string $name, bool $read, bool $download): array
    {
        $pathInfo = pathinfo($path);
        if ($read) {
            [$count, $readUsers] = AuditReadLogic::getReadNum('', $path);
            $readHtml = '(' . ($count ?? 0) . ')：' . ($readUsers ?? '');
        }
        if ($download){
            $downloadHtml = '<a href="' . admin_url('file/download/' . urlencode(base64_encode($path))) . '"  target="_blank">
            <span class="feather icon-download">' .
                trans('common.download') . '</a>';
        }
        if (empty($name)) {
            $name = Attachements::getFileName($pathInfo['filename']);
            $name = empty($name) ? $pathInfo['basename'] : $name;
        }

        $url = config('admin.file_preview')['url'];
        $preview = $url . '/' . urlencode(base64_encode($path));
        $attach = Attachements::query()->where('path', $path)->first();

        $res = [
            'user'=>$attach->user_id?AdminUserLogic::getUserById($attach->user_id,'name'):'',
            'created_at'=>$attach->created_at,
            'url'=>$preview,
            'name'=>$name,
            'download_url'=>admin_url('file/download/' . urlencode(base64_encode($path))),
            'downloadHtml'=>$downloadHtml??'',
            'readHtml'=>$readHtml??'',
        ];
        return $res;
    }
    /**
     * @param string $path
     * @return string
     */
    private static function singleFilePreviewHtml(string $path, string $name, bool $read, bool $download): string
    {
        $pathInfo = pathinfo($path);
        if ($read) {
            [$count, $readUsers] = AuditReadLogic::getReadNum('', $path);
            $readHtml = '已阅(' . ($count ?? 0) . ')：' . ($readUsers ?? '');
        }
        if ($download){
            $downloadHtml = '<a href="' . admin_url('file/download/' . urlencode(base64_encode($path))) . '"  target="_blank">' .
                trans('common.download') . '</a>';
        }
        if (empty($name)) {
            $name = Attachements::getFileName($pathInfo['filename']);
            $name = empty($name) ? $pathInfo['basename'] : $name;
        }

        $url = config('admin.file_preview')['url'];
        $preview = $url . '/' . urlencode(base64_encode($path));

        return '  <span>' .
            $name . '</span>&nbsp;&nbsp;<a href="' . $preview . '" target="_blank">' .
            trans('common.view') . '</a>&nbsp;&nbsp;'. ($downloadHtml ?? '').'&nbsp;&nbsp;&nbsp;&nbsp;' . ($readHtml ?? '') . '<br/>';
    }

    /**
     * @param string $path
     * @return array
     */
    public static function loadFileToArray(string $path): array
    {
        return array_reduce(
            glob($path),
            fn($carry, $v) => array_merge($carry, include $v),
            []
        );
    }

    /**
     * @param int $column
     * @return string
     */
    public static function convertIntToExcelColumn(int $column): string
    {
        $count = intval($column / 26);
        $mod = $column % 26;

        return str_repeat('A', $count) . chr(64 + $mod);
    }

    /**
     * 判断是否是银行卡号
     * @param $bankCardNum
     * @return bool
     */
    public static function checkBankCard($bankCardNum):bool
    {
        $len = strlen($bankCardNum);
        if($len != 16 && $len != 19){
            return false;
        }
        //使用Luhn算法验证银行卡号
        $sum = 0;
        for($i = 0;$i < $len;$i++){
            $digit = (int) $bankCardNum[$i];
            if($i % 2 == $len % 2){
                $digit = $digit * 2;
                if($digit > 9){
                    $digit = $digit - 9;
                }
            }
            $sum += $digit;
        }
        return $sum % 10 == 0;
    }

    public static function subTree(array $data,int $pid = 0,$sonField = 'sub')
    {
        // 返回的结果
        $arr = [];
        foreach ($data as $val) {
            // 给定的PID是当前记录的上级ID
            if ($pid == $val['pid']) {
                // 递归
                $val[$sonField] = self::subTree($data,$val['id'],$sonField);
                $arr[] = $val;
            }
        }
        return $arr;
    }
    public static  function subTreeBack(array $tree){
        $data = [];
        foreach($tree as $val){
            $this_val = $val;
            unset($this_val['sub']);
            $data[] = $this_val;
            if(!empty($val['sub'])){
                $array = self::subTreeBack($val['sub']);
                $data = array_merge($data,$array);
            }
        }
        return $data;
    }

    public static function getDates($days){
        $dates = [];
        for ($i = 0; $i < $days; $i++) {
            $date = Carbon::now()->subDays($i)->toDateString();
            $dates[] = $date;
        }
        return $dates;
    }

    //去掉域名得到相对uri
    public static function getRelativelyUrl($url):string
    {
        $host = parse_url($url, PHP_URL_HOST);
        $cleanUrl = Str::replaceFirst($host, '', $url);
        return preg_replace('/^https?:\/\//', '', $cleanUrl);
    }

    public static function statusButton($status,array $payload,$lable=[0=>'未完成',1=>'进行中',2=>'完成'])
    {
        $url = Audit::getAuditUrl($payload);
        if($status==2){
            return '<span style="cursor: pointer">
                    <a href="'.$url.'" target="_blank">
                        <span class="label" style="background:#4e9876">'.$lable[$status].'</span>
                    </a>
                </span>';
        }else{
            return '<span style="cursor: pointer">
                    <a href="'.$url.'" target="_blank">
                        <span class="label" style="background:#d2d6de;color: #555">'.$lable[$status].'</span>
                    </a>
                </span>';
        }

    }

    public static function generateUniqueWorkOrderNumber() {
        $workOrderNumber = self::generateWorkOrderNumber();
        while (Cache::has($workOrderNumber)) {
            $workOrderNumber = self::generateWorkOrderNumber();
        }

        Cache::forever($workOrderNumber, true);

        return $workOrderNumber;
    }

    public static function generateWorkOrderNumber() {
        $prefix = 'WO-' . date('Ymd') . '-';
        $randomNumber = mt_rand(1000, 9999);
        $workOrderNumber = $prefix . $randomNumber;
        return $workOrderNumber;
    }
}
